import { clone } from './functions/util';
import { checkCondition } from './functions/condition';
import { $$event } from './global';

export class Achievement {
    #achievements: any;
    constructor() { }

    // 时机
    Opportunity = {
        START: "START",             // 分配完成点数，点击开始新人生后
        TRAJECTORY: "TRAJECTORY",   // 每一年的人生经历中
        SUMMARY: "SUMMARY",         // 人生结束，点击人生总结后
        END: "END",                 // 游戏完成，点击重开 重开次数在这之后才会+1
    };


    initial({ achievements }: { achievements: any }) {
        this.#achievements = achievements;
    }

    count() {
        return Object.keys(this.#achievements).length;
    }

    list(property: any) {
        return Object
            .values(this.#achievements)
            .map(({
                id, name, opportunity,
                description, hide, grade,
            }: any) => ({
                id, name, opportunity,
                description, hide, grade,
                isAchieved: this.isAchieved(id, property),
            }));
    }

    get(achievementId: any) {
        const achievement = this.#achievements[achievementId];
        if (!achievement) throw new Error(`[ERROR] No Achievement[${achievementId}]`);
        return clone(achievement);
    }

    check(achievementId: any, property: any) {
        const { condition } = this.get(achievementId);
        return checkCondition(property, condition);
    }

    isAchieved(achievementId: any, property: any) {
        for (const [achieved] of (property.get(property.TYPES.ACHV) || []))
            if (achieved == achievementId) return true;
        return false;
    }

    achieve(opportunity: any, property: any) {
        this.list(property)
            .filter(({ isAchieved }) => !isAchieved)
            .filter(({ opportunity: o }) => o == opportunity)
            .filter(({ id }) => this.check(id, property))
            .forEach(({ id }) => {
                property.achieve(property.TYPES.ACHV, id)
                $$event('achievement', this.get(id))
            });
    }
}